package leetcode.list;

import java.util.List;

/**
 * 给你链表的头结点 head ，请将其按 升序 排列并返回 排序后的链表 。
 *
 *
 *
 * 示例 1：
 *
 *
 * 输入：head = [4,2,1,3]
 * 输出：[1,2,3,4]
 * 示例 2：
 *
 *
 * 输入：head = [-1,5,3,4,0]
 * 输出：[-1,0,3,4,5]
 * 示例 3：
 *
 * 输入：head = []
 * 输出：[]
 *
 *
 * 提示：
 *
 * 链表中节点的数目在范围 [0, 5 * 104] 内
 * -105 <= Node.val <= 105
 *
 *
 * 进阶：你可以在 O(n log n) 时间复杂度和常数级空间复杂度下，对链表进行排序吗？
 */
public class LeetCode148_SortList {
    public ListNode sortList(ListNode head) {
        ListNode th = head;
        if (th == null || th.next == null) {
            return th;
        }
        // 节点个数
        int n = 0;
        while (th != null) {
            n++;
            th = th.next;
        }
        // 最大步长
        int maxStep = (n / 2) * 2;
        for (int i = 1; i <= maxStep; i *= 2) {
            for (int j = 0; j < n; j += 2 * i) {
                merge(getIndexNode(head, j), i);
            }
        }
        return head;
    }

    public ListNode getIndexNode(ListNode head, int index) {
        ListNode th = head;
        while (index > 0 && th != null) {
            index--;
            th = th.next;
        }
        return th;
    }

    public void merge(ListNode p, int step) {
        // 第二段的起点
        int pStep = step;
        ListNode q = p;
        for (int i = 0; i < step && q != null; i++) {
            q = q.next;
        }
        // 分别以p,q为起点开始合并
        while (step > 0 && q != null) {
            if (p.val <= q.val ) {
                p = p.next;
            }
            // 较小值换到前面
            if (p != null && p.val > q.val) {
                int tempStep = pStep;
                int v = p.val;
                p.val = q.val;
                q.val = v;
                p = p.next;
                // 移动当前的q值
                ListNode tq = q;
                while (tq != null && tempStep > 1) {
                    ListNode tqn = tq.next;
                    if (tqn != null && tqn.val < tq.val) {
                        int tqv = tq.val;
                        tq.val = tqn.val;
                        tqn.val = tqv;
                        tq = tqn;
                        tempStep--;
                    }else {
                        break;
                    }
                }
            }
            step--;
        }
    }

    public static void main(String[] args) {
        ListNode a = new ListNode(4);
        ListNode a2 = new ListNode(2);
        a.next = a2;
        ListNode a3 = new ListNode(1);
        a2.next = a3;
        ListNode a4 = new ListNode(3);
        a3.next = a4;
//        ListNode a5 = new ListNode(5);
//        a4.next = a5;

        LeetCode148_SortList leetCode148SortList = new LeetCode148_SortList();
        ListNode listNode = leetCode148SortList.sortList(a);

    }
}
